using System;
using System.Collections.Generic;
using System.Threading;

using Clandestine.Audio;

namespace nicotine
{
	public partial class Interpreter
	{
		private void print(string sound, int appearance, string message)
		{
			Sound snd = null;
			
			if (sound.ToLower() != "none")
			{
				snd = new Sound(this.audio, sound);
				snd.Play();
			}
			
			if (message.Contains("${"))
				foreach (string nam in counters.Keys)
					message = message.Replace("${" + nam + "}", counters[nam].ToString());
			
			Typewriter.WriteLine((TypeAppearance)appearance, message);
			
			if (snd != null)
			{
				// in case of accidental keypresses and the like, erase the buffer.
				while (Console.KeyAvailable)
					Console.ReadKey();
				
				// write skip hint
				int tx = Console.CursorTop;
				Console.WriteLine("(Press [Tab] to skip this paragraph.)");
				
				// now, wait until either snd finishes playing or the user presses [Tab] to skip the speech..
				while (snd.Playing && (!(Console.KeyAvailable && (Console.ReadKey().Key == ConsoleKey.Tab))))
					Thread.Sleep(50);
				
				// erase skip hint
				Console.SetCursorPosition(0, tx);
				Console.WriteLine("                                     ");
				Console.SetCursorPosition(0, tx);
				
				// stop if necessary!!
				if (snd.Playing)
					snd.Stop();
				
				snd.Dispose();
			}
		}
		
		private void setMusic(string sound)
		{
			// TODO: Fade-out! allow more than one track!!
			if (music != null)
			{
				music.Stop();
				music.Dispose();
				music = null;
			}
			
			if (sound != "none")
				music = new Sound(this.audio, sound);
		}
		
		private void fx(int fx)
		{
			Typewriter.PerformFx((TypeFx)fx);
		}
		
		private void ifFlag(bool not, string flagName, string action)
		{
			bool b = (flags[flagName] != not);
			
			if (b)
				runLine(action);
		}
		
		private void ifCounter(bool not, string counterName, string operation, int comparatee, string action)
		{
			bool b;
			int c = counters[counterName];
			
			switch (operation)
			{
				case "=":
				case "==":
					b = (c == comparatee);
					break;
				case ">":
					b = (c > comparatee);
					break;
				case "<":
					b = (c < comparatee);
					break;
				case ">=":
					b = (c >= comparatee);
					break;
				case "<=":
					b = (c <= comparatee);
					break;
				case "!=":
				case "<>":
				case "~=":
					b = (c != comparatee);
					break;
				default:
					throw new Exception("Error at line " + currLine.ToString() + ": in if counter, I don't know how to do operation `" + operation + "'!\n"
					                    + "(Expected one of =,== or > or < or >= or <= or !=,<>,~=)");
			}
			
			if (not ? !b : b)
				runLine(action);
		}
		
		private void setFlag(string flagName, bool high)
		{
			flags[flagName] = high;
		}
		
		private void setCounter(string counterName, int val)
		{
			counters[counterName] = val;
		}
		
		private void addCounter(string counterName, int val)
		{
			counters[counterName] += val;
		}
		
		private void subCounter(string counterName, int val)
		{
			counters[counterName] -= val;
		}
		
		private void mulCounter(string counterName, int val)
		{
			counters[counterName] *= val;
		}
		
		private void divCounter(string counterName, int val)
		{
			counters[counterName] /= val;
		}
		
		private void incCounter(string counterName)
		{
			counters[counterName]++;
		}
		
		private void decCounter(string counterName)
		{
			counters[counterName]--;
		}
		
		private void jump(string labelName)
		{
			currLine = labels[labelName];
		}
		
		private void call(string labelName)
		{
			stack.Push(currLine);
			currLine = labels[labelName];
		}
		
		private void rtn()
		{
			currLine = stack.Pop();
		}
		
		private void actionDescription(string powerWord, string desc)
		{
			actionDescriptions.Add(powerWord.ToUpper(), desc);
		}
		
		private void actionDo(string powerWord, string action)
		{
			actionActions.Add(powerWord.ToUpper(), action);
		}
		
		private void prompt(int ta)
		{
			bool z = false;
			
			while (!z)
			{
				foreach (string k in actionDescriptions.Keys)
					Typewriter.WriteLine((TypeAppearance)ta, k.ToUpper() + ": " + actionDescriptions[k]);
				
				Console.WriteLine("What would you like to do?");
				Console.Write(">");
				
				string kw = Console.ReadLine().Trim().Split(' ')[0].ToUpper();
				
				z = true;
				
				if (actionActions.ContainsKey(kw))
					runLine(actionActions[kw]);
				else // SIGH
				{
					// Can we identify by first alphabetical letter?
					List<char> uniqueLetters = new List<char>();
					foreach (string k in actionActions.Keys)
					{
						if (!uniqueLetters.Contains(k[0]))
							uniqueLetters.Add(k[0]);
						else
						{
							z = false;
							break;
						}
					}
					
					if (z)
					{
						// Ok, this means we CAN uniquely identify actions by their first letters.
						// So, let's do this!
						char l = kw[0];
						
						z = false;
						foreach (string k in actionActions.Keys)
							if (k[0] == l)
							{
								Console.WriteLine("[Assuming you meant `" + k + "'.]\n");
								runLine(actionActions[k]);
								z = true;
								break;
							}
					}
					
					if (!z)
						Console.WriteLine("Sorry, I don't understand `" + kw + "' - please try again. Look at the action you want to do, then type the word that is in capitals at the start of the line.\n");
					
				}
			}
			
			actionDescriptions.Clear();
			actionActions.Clear();
			
		}
		
	}
}
